package com.quick.android.ui;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.FrameLayout;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public abstract class BaseFragment extends Fragment {
    public static final int RESULT_OK = -1;
    public static final int RESULT_CANCELED = 0;
    private LayoutInflater mInflater;
    private ViewGroup mRootView;
    private ViewGroup mDecorView;
    private View mContentView;
    private int mRequestCode = 0;
    private int mResultCode = 0;
    private Intent mResultData;
    protected FragmentManager mChildFManager;
    private HashMap<Integer, ArrayList<String>> mStackFragments;
    private HashMap<Integer, String> mCurrentFragments;
    private int mResId = -1;

    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            this.mRequestCode = bundle.getInt("BaseFragment_requestCode", 0);
        }
    }

    public final View onCreateView(LayoutInflater inflater,
                                   ViewGroup container, Bundle savedInstanceState) {
        this.mInflater = inflater;
        this.mRootView = container;
        this.mDecorView = new FrameLayout(getActivity());
        return this.mDecorView;
    }

    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @SuppressLint({"UseSparseArrays"})
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        this.mChildFManager = getChildFragmentManager();
        if (savedInstanceState != null) {
            this.mStackFragments = ((HashMap) savedInstanceState
                    .get("BaseFragment_mStackFragments"));
            this.mCurrentFragments = ((HashMap) savedInstanceState
                    .get("BaseFragment_mCurrentFragments"));
        }
        if (this.mStackFragments == null) {
            this.mStackFragments = new HashMap();
        }
        if (this.mCurrentFragments == null) {
            this.mCurrentFragments = new HashMap();
        }
        for (Map.Entry<Integer, String> entry : this.mCurrentFragments
                .entrySet()) {
            int resId = ((Integer) entry.getKey()).intValue();
            String tag = (String) entry.getValue();
            changeFragment(resId, findFragmentByTag(resId, tag), tag);
        }
        initCreate(savedInstanceState);
    }

    protected void initCreate(Bundle savedInstanceState) {
        initViews();
        initData(savedInstanceState);
    }

    /**
     * 初始化界面和控件
     */
    public abstract void initViews();

    /**
     * 初始化数据
     */
    public abstract void initData(Bundle savedInstanceState);

    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable("BaseFragment_mStackFragments",
                this.mStackFragments);
        outState.putSerializable("BaseFragment_mCurrentFragments",
                this.mCurrentFragments);
    }

    public ViewGroup getRootView() {
        return this.mRootView;
    }

    public void setContentView(int layoutResID) {
        this.mContentView = this.mInflater.inflate(layoutResID,
                this.mDecorView, false);
        this.mDecorView.addView(this.mContentView);
    }

    public void setContentView(View view) {
        this.mContentView = view;
        this.mDecorView.addView(this.mContentView);
    }

    public View getContentView() {
        return this.mContentView;
    }

    public View findViewById(int id) {
        return this.mContentView.findViewById(id);
    }

    public final void startFragment(Intent intent) {
        try {
            String className = intent.getComponent().getClassName();
            if ((getActivity() instanceof BaseFragmentActivity)) {
                BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
                BaseFragment fragment = (BaseFragment) Class.forName(className)
                        .newInstance();
                fragment.setArguments(intent.getExtras());
                activity.putFragment(fragment, fragment.getClass().getName());
            } else {
                throw new IllegalArgumentException(
                        "Intent ComponentName must be a BaseFragmentActivity Class ");
            }
        } catch (Exception localException) {
        }
    }

    public final void startFragmentForResult(Intent intent, int requestCode) {
        String code = intent.getStringExtra("BaseFragment_requestCode");
        if (code != null) {
            throw new IllegalArgumentException(
                    "Intent params can't named BaseFragment_requestCode");
        }
        intent.putExtra("BaseFragment_requestCode", requestCode);
        startFragment(intent);
    }

    public void onFragmentResult(int requestCode, int resultCode, Intent data) {
    }

    public final void setResult(int resultCode) {
        this.mResultCode = resultCode;
    }

    public final void setResult(int resultCode, Intent data) {
        this.mResultCode = resultCode;
        this.mResultData = data;
    }

    public final void finish() {
        BaseFragment fragment = null;

        BaseFragment parentFragment = (BaseFragment) getParentFragment();
        if (parentFragment != null) {
            fragment = parentFragment.popFragment();
            if (fragment != null) {
                fragment.onFragmentResult(this.mRequestCode, this.mResultCode,
                        this.mResultData);
            }
        } else {
            BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
            fragment = activity.popFragment();
            if (fragment != null) {
                fragment.onFragmentResult(this.mRequestCode, this.mResultCode,
                        this.mResultData);
            }
        }
    }

    public void onBackPressed() {
        ArrayList<String> stack = (ArrayList) this.mStackFragments.get(Integer
                .valueOf(this.mResId));
        if ((stack == null) || (stack.size() == 0)) {
            finish();
        } else {
            String top = (String) stack.get(stack.size() - 1);
            BaseFragment fragment = findFragmentByTag(this.mResId, top);
            fragment.onBackPressed();
        }
    }

    public void onDestroy() {
        super.onDestroy();
    }

    public int size() {
        return size(this.mResId);
    }

    public int size(int resId) {
        ArrayList<String> stack = (ArrayList) this.mStackFragments.get(Integer
                .valueOf(resId));
        if (stack == null) {
            return 0;
        }
        return stack.size();
    }

    public final void setFragmentViewId(int resId) {
        this.mResId = resId;
    }

    public final BaseFragment findFragmentById() {
        return findFragmentById(this.mResId);
    }

    public final BaseFragment findFragmentById(int resId) {
        return (BaseFragment) this.mChildFManager.findFragmentById(resId);
    }

    public final BaseFragment findFragmentByTag(String tag) {
        return findFragmentByTag(this.mResId, tag);
    }

    public final BaseFragment findFragmentByTag(int resId, String tag) {
        return (BaseFragment) this.mChildFManager.findFragmentByTag(resId + "@"
                + tag);
    }

    public final BaseFragment getCurrentFragment() {
        return getCurrentFragment(this.mResId);
    }

    public final BaseFragment getCurrentFragment(int resId) {
        return findFragmentByTag(resId,
                (String) this.mCurrentFragments.get(Integer.valueOf(resId)));
    }

    public void onCreateAnimation(int resId, BaseFragment enterFragment,
                                  BaseFragment exitFragment, FragmentTransaction transaction,
                                  boolean remove) {
    }

    @Deprecated
    public final Animation onCreateAnimation(int transit, boolean enter,
                                             int nextAnim) {
        return super.onCreateAnimation(transit, enter, nextAnim);
    }

    public final BaseFragment replaceFragment(BaseFragment fragment) {
        return replaceFragment(this.mResId, fragment, fragment.getClass()
                .getName());
    }

    public final BaseFragment replaceFragment(int resId, BaseFragment fragment) {
        return replaceFragment(resId, fragment, fragment.getClass().getName());
    }

    public final BaseFragment replaceFragment(BaseFragment fragment, String tag) {
        return replaceFragment(this.mResId, fragment, tag);
    }

    public final BaseFragment replaceFragment(int resId, BaseFragment fragment,
                                              String tag) {
        FragmentTransaction ft = this.mChildFManager.beginTransaction();

        BaseFragment exitFragment = null;
        String exitTag = (String) this.mCurrentFragments.get(Integer
                .valueOf(resId));
        if (exitTag != null) {
            exitFragment = findFragmentByTag(resId, exitTag);
        }
        onCreateAnimation(resId, fragment, exitFragment, ft, false);
        this.mCurrentFragments.put(Integer.valueOf(resId), tag);

        ft.replace(resId, fragment, resId + "@" + tag);
        ft.commitAllowingStateLoss();

        return fragment;
    }

    public final BaseFragment changeFragment(BaseFragment fragment) {
        return changeFragment(this.mResId, fragment, fragment.getClass()
                .getName());
    }

    public final BaseFragment changeFragment(int resId, BaseFragment fragment) {
        return changeFragment(resId, fragment, fragment.getClass().getName());
    }

    public final BaseFragment changeFragment(BaseFragment fragment, String tag) {
        return changeFragment(this.mResId, fragment, tag);
    }

    public final BaseFragment changeFragment(int resId, BaseFragment fragment,
                                             String tag) {
        FragmentTransaction ft = this.mChildFManager.beginTransaction();
        BaseFragment exitFragment = null;
        String exitTag = (String) this.mCurrentFragments.get(Integer
                .valueOf(resId));
        if (exitTag != null) {
            exitFragment = findFragmentByTag(resId, exitTag);
        }
        onCreateAnimation(resId, fragment, exitFragment, ft, false);
        this.mCurrentFragments.put(Integer.valueOf(resId), tag);
        if (this.mChildFManager.getFragments() != null) {
            for (Fragment f : this.mChildFManager.getFragments()) {
                if ((f != null) && (f.getId() == resId)) {
                    ft.hide(f);
                }
            }
        }
        if (findFragmentByTag(resId, tag) == null) {
            ft.add(resId, fragment, resId + "@" + tag);
        } else {
            fragment = findFragmentByTag(resId, tag);
        }
        ft.show(fragment);
        ft.commitAllowingStateLoss();

        return fragment;
    }

    public final BaseFragment putFragment(BaseFragment fragment) {
        return putFragment(this.mResId, fragment, fragment.getClass().getName());
    }

    public final BaseFragment putFragment(int resId, BaseFragment fragment) {
        return putFragment(resId, fragment, fragment.getClass().getName());
    }

    public final BaseFragment putFragment(BaseFragment fragment, String tag) {
        return putFragment(this.mResId, fragment, tag);
    }

    public final BaseFragment putFragment(int resId, BaseFragment fragment,
                                          String tag) {
        ArrayList<String> stack = (ArrayList) this.mStackFragments.get(Integer
                .valueOf(resId));
        if (stack == null) {
            stack = new ArrayList();
            this.mStackFragments.put(Integer.valueOf(resId), stack);
        }
        tag = tag + "#" + stack.size();

        FragmentTransaction ft = this.mChildFManager.beginTransaction();
        BaseFragment exitFragment = null;
        String exitTag = (String) this.mCurrentFragments.get(Integer
                .valueOf(resId));
        if (exitTag != null) {
            exitFragment = findFragmentByTag(resId, exitTag);
        }
        onCreateAnimation(resId, fragment, exitFragment, ft, false);
        this.mCurrentFragments.put(Integer.valueOf(resId), tag);
        if (this.mChildFManager.getFragments() != null) {
            for (Fragment f : this.mChildFManager.getFragments()) {
                if ((f != null) && (f.getId() == resId)) {
                    ft.hide(f);
                }
            }
        }
        ft.add(resId, fragment, resId + "@" + tag);
        ft.commitAllowingStateLoss();

        stack.add(tag);

        return fragment;
    }

    public final BaseFragment popFragment() {
        return popFragment(this.mResId);
    }

    public final BaseFragment popFragment(int resId) {
        ArrayList<String> stack = (ArrayList) this.mStackFragments.get(Integer
                .valueOf(resId));
        if ((stack == null) || (stack.size() <= 1)) {
            finish();
            return null;
        }
        String exitTag = (String) stack.get(stack.size() - 1);
        String enterTag = (String) stack.get(stack.size() - 2);

        FragmentTransaction ft = this.mChildFManager.beginTransaction();
        BaseFragment enterFragment = findFragmentByTag(resId, enterTag);
        BaseFragment exitFragment = findFragmentByTag(resId, exitTag);
        onCreateAnimation(resId, enterFragment, exitFragment, ft, true);

        ft.remove(exitFragment);
        ft.show(enterFragment);
        ft.commitAllowingStateLoss();

        this.mCurrentFragments.put(Integer.valueOf(resId), enterTag);
        stack.remove(stack.size() - 1);

        return enterFragment;
    }

    public final BaseFragment removeFragment(BaseFragment fragment) {
        return removeFragment(this.mResId, fragment, fragment.getClass()
                .getName());
    }

    public final BaseFragment removeFragment(int resId, BaseFragment fragment) {
        return removeFragment(resId, fragment, fragment.getClass().getName());
    }

    public final BaseFragment removeFragment(BaseFragment fragment, String tag) {
        return removeFragment(this.mResId, fragment, tag);
    }

    public final BaseFragment removeFragment(int resId, BaseFragment fragment,
                                             String tag) {
        FragmentTransaction ft = this.mChildFManager.beginTransaction();
        ft.remove(fragment);
        ft.commitAllowingStateLoss();
        return fragment;
    }
}
